x = 42
print(type(x))
y = 'hello'
print(type(y))
def z():
pass
print(type(z))
import math
print(type(math))
print(type(type))<class 'int'>
<class 'str'>
<class 'function'>
<class 'module'>
<class 'type'>
Jan 11, 2024
A paradigm in which data and operations are modeled as intimately paired, rather than as separate elements.
A group of objects that share commonality in their underlying encoding and supported behaviors.s are modeled as intimately paired, rather than as separate elements.
An object has state, behavior, and identity; the structure and behavior of similar objects are defined in their common class. Some things are not objects, but are attributes; e.g. age, color. Attributes may be properties of some object.
A single object drawn from a given class.
One of the pieces of data used in representing the state of an object. Equivalently termed
a data member, field, or instance variable
A formal operation supported by all objects of a given class.
A blueprint to make objects
# Example 1: Creating Class and Object in Python
class Person:
"This is a person class"
age = 10
def greet(self):
print('Hello')
print(Person.age) # Output: 10
print(Person.greet) # Output: <function Person.greet>
print(Person.__doc__) # Output: 'This is my second class'10
<function Person.greet at 0x000001F9695FE0E0>
This is a person class
An instance of a Class
Constructors are methods that are useful for any kind of initialization you want to perform with the objects. Note:
A constructor is executed as soon as an object of a class is instantiated
class Employee: # Class definition
'Common base class for all employees' # Docstring
empCount = 0 # Class variable
def __init__(self, name, salary): # constructor method
self. name = name # instance variable
self. salary = salary # instance variable
Employee. empCount += 1
def displayCount(self): # instance method
print ("Total Employee %d" % Employee. empCount)
def displayEmployee(self):
print ("Name : ", self. name, ", Salary: " , self. salary)
def __str__(self): #special method
return f'The name is {self.name} and salary is {self.salary}'
class Worker(Employee):
passemp1 = Employee("Zara", 2000) # First object
emp2 = Employee("Manni", 5000) # Second object
emp1.displayEmployee() # Method
emp2.displayEmployee() # Method
print(emp1)
print(emp2)
print(hasattr(emp1, 'salary' )) # Returns true if 'salary' attribute exists
print(getattr(emp1, 'salary' )) # Returns value of 'salary' attribute
print(setattr(emp1, 'age' , 8)) # Set attribute 'age' at 8
print(emp1.age)
print(delattr(emp1, 'salary' )) # Delete attribute 'age'
print ("Employee.__doc__:", Employee. __doc__)
print ("Employee.__name__:", Employee. __name__)
print ("Employee.__module__:", Employee. __module__)
print ("Employee.__bases__:", Employee. __bases__)
print ("Employee.__dict__:", Employee. __dict__ )
print(isinstance(emp1,Employee))
print(issubclass(Worker,Employee))Name : Zara , Salary: 2000
Name : Manni , Salary: 5000
The name is Zara and salary is 2000
The name is Manni and salary is 5000
True
2000
None
8
None
Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__doc__': 'Common base class for all employees', 'empCount': 2, '__init__': <function Employee.__init__ at 0x00000189AD9E90D0>, 'displayCount': <function Employee.displayCount at 0x00000189AD9E9280>, 'displayEmployee': <function Employee.displayEmployee at 0x00000189AD9E9310>, '__str__': <function Employee.__str__ at 0x00000189AD9E93A0>, '__dict__': <attribute '__dict__' of 'Employee' objects>, '__weakref__': <attribute '__weakref__' of 'Employee' objects>}
True
True
self in Python?In object-oriented programming, whenever we define methods for a class, we use self as the first parameter in each case. Let’s look at the definition of a class called Point.the method call p1.distance() is actually equivalent to Point.distance(p1).
class Point(object):
def __init__(self,x = 0,y = 0):
self.x = x
self.y = y
def distance(self):
"""Find distance from origin"""
return (self.x**2 + self.y**2) ** 0.5
p1 = Point(6,9)
print(p1.distance())
print(type(Point.distance))
print(type(p1.distance))10.816653826391969
<class 'function'>
<class 'method'>
By now you are clear that the object (instance) itself is passed along as the first argument, automatically. This implicit behavior can be avoided while making a static method. Consider the following simple example:
Here, @staticmethod is a function decorator that makes stat_meth() static. Let us instantiate this class and call the method.
class Student:
'Common base class for all students'
student_count=0
def __init__(self, name, id):
self.name = name
self.id = id
Student.student_count+=1
def printStudentData(self):
print ("Name : ", self.name, ", Id : ", self.id)
std1=Student("Milan",101)
std2=Student("Vijay",102)
std3=Student("Chirag",103)
print("Total Student : ",Student.student_count)
print ("Student.__doc__:", Student.__doc__)
print ("StudentStudent.__name__:", Student.__name__)
print ("Student.__module__:", Student.__module__)
print ("Student.__bases__:", Student.__bases__)
print ("Student.__dict__:", Student.__dict__)Total Student : 3
Student.__doc__: Common base class for all students
StudentStudent.__name__: Student
Student.__module__: __main__
Student.__bases__: (<class 'object'>,)
Student.__dict__: {'__module__': '__main__', '__doc__': 'Common base class for all students', 'student_count': 3, '__init__': <function Student.__init__ at 0x000001F9695FE680>, 'printStudentData': <function Student.printStudentData at 0x000001F9695FEA70>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>}
A variable of class shared by all instances
class Person:
species = 'Homo sapiens'
count = 0
def __init__(self,name,age):
self.name = name
self.age = age
Person.count+=1
def display(self):
print(f'{self.name} is {self.age} years old')
p1 = Person('John',20)
p2 = Person('Jack',34)
p1.display()
p2.display()
print(Person.count)
p3=Person('Jill', 40)
p4=Person('Jane', 35)
print(Person.count) John is 20 years old
Jack is 34 years old
2
4
A variable defined inside class which can only be accessed by current instance
class YourClass(object):
classy = "class value"
dd = YourClass()
print(dd.classy) # < This should return the string "class value"
dd.classy = "Instance value"
print(dd.classy) # This should return the string "Instance value"
# This will delete the value set for 'dd.classy' in the instance.
del dd.classy
# Since the overriding attribute was deleted, this will print 'class value'.
print(dd.classy)class value
Instance value
class value
# The internal representation of an object of foo class ➀–➅ is hidden outside the class → Encapsulation.
class foo:
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a * self.b
# Any accessible member (data/method) of an object of foo is restricted and can only be accessed by that object
# Implementation of add() method is hidden → Abstraction.
foo_object = foo(3,4)
foo_object.add()12
image.png
image.png
# Data Hiding
class MyClass(object): # Defining class
def __init__(self, x, y, z): # Constructor method
self.var1 = x # public data member
self._var2 = y # protected data member
self.__var3 = z # private data member
obj = MyClass(3,4,5)
print(obj.var1)
print(obj._var2)
# print(obj.__var3)
print(obj._MyClass__var3)3
4
5
Class.method(instance) does the same thing as instance.method()'hello'.lower() is the same as str.lower('hello').URL: https://github.com/
Founding year: 2008
Free to use: True
class Website:
def info(self): # self will be github
print("URL:", self.url)
print("Founding year:", self.founding_year)
print("Free to use:", self.free_to_use)
github = Website()
github.url = 'https://github.com/'
github.founding_year = 2008
github.free_to_use = True
github.info()URL: https://github.com/
Founding year: 2008
Free to use: True
class Website:
def initialize(self, url, founding_year, free_to_use):
self.url = url
self.founding_year = founding_year
self.free_to_use = free_to_use
def info(self):
print("URL:", self.url)
print("Founding year:", self.founding_year)
print("Free to use:", self.free_to_use)
github = Website()
github.initialize('https://github.com/', 2008, True)
github.info()URL: https://github.com/
Founding year: 2008
Free to use: True
__init__ constructorclass Website:
def __init__(self, url, founding_year, free_to_use):
self.url = url
self.founding_year = founding_year
self.free_to_use = free_to_use
def info(self):
print("URL:", self.url)
print("Founding year:", self.founding_year)
print("Free to use:", self.free_to_use)
github = Website('https://github.com/', 2008, True)
github.info()URL: https://github.com/
Founding year: 2008
Free to use: True
In object-oriented programming (OOP) with Python, a destructor is a special method that is automatically called when an object is about to be destroyed or deallocated. It is used to clean up resources or perform any necessary cleanup operations before the object is removed from memory.
In Python, the destructor method is named __del__.
__del__ method for cleanup is not always recommended. It’s more common to use context managers (with the with statement) or other mechanisms for resource management in Python. The __del__ method is called by the garbage collector, and the exact timing of its execution is not guaranteed.The generators offer a comfortable method to generate iterators, and that's why they are called generators.
Method of working:
yield returns the value of the expression, which is following the keyword yield. This is like a function, but Python keeps track of the position of this yield and the state of the local variables is stored for the next call. At the next call, the execution continues with the statement following the yield statement and the variables have the same values as they had in the previous call.def city_generator():
yield "Hamburg"
yield "Konstanz"
yield "Berlin"
yield "Zurich"
yield "Schaffhausen"
yield "Stuttgart"
city = city_generator()
print(next(city))
print(next(city))
print(next(city))
print(next(city))
print(next(city))
print(next(city))
print(next(city))Hamburg
Konstanz
Berlin
Zurich
Schaffhausen
Stuttgart
StopIteration:
def fibonacci(n):
""" A generator for creating the Fibonacci numbers """
a, b, counter = 0, 1, 1
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(6)
for x in f:
print(x, " ", end="") # 0 1 1 2 3 5
Manish Patel